﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Reflection.Core;
using System.Reflection;
using Pixysoft.Framework.Reflection.Controller;
using Pixysoft.Framework.Verifications;
using System.Threading;

namespace Pixysoft.Framework.Reflection
{
    /// <summary>
    /// 线程安全
    /// </summary>
    public class ReflectionManager
    {
        public static bool OutputToConsole
        {
            set { LoggerHelper.OutputToConsole = value; }
        }

        /// <summary>
        /// 创建动态方法调用的handler
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IDynamicType CreateDynamicType(Type type)
        {
            return new DynamicType(type);
        }

        /// <summary>
        /// 序列化为结构描述
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IDummyType CreateDummyType(Type type)
        {
            if (type == null)
                throw Exceptions.VerificationFailedException(type);

            string nameSpace = type.Namespace;

            string fullName = type.FullName;

            string name = type.Name;

            return DummyTypeHandlerFactory.CreateDummyTypeObject(nameSpace, fullName, name, type);
        }

        /// <summary>
        /// 创建对象的hash映射体
        /// </summary>
        /// <param name="target"></param>
        public static IBeanMap CreateBeanMap(object target)
        {
            if (target == null)
                return null;

            Type targetType = target.GetType();

            string setkey = StringHelper.default_name_cache_bean_set + targetType.Namespace + targetType.FullName + targetType.Name;

            string getkey = StringHelper.default_name_cache_bean_get + targetType.Namespace + targetType.FullName + targetType.Name;

            BeanMapFactory.SetBeanHandler setHandler = null;

            DynamicCacheFactory<string, BeanMapFactory.SetBeanHandler>.Instance.WriteLock();

            try
            {
                if (DynamicCacheFactory<string, BeanMapFactory.SetBeanHandler>.Instance.Contains(setkey))
                {
                    setHandler = DynamicCacheFactory<string, BeanMapFactory.SetBeanHandler>.Instance.GetValue(setkey);
                }

                if (setHandler == null)
                {
                    setHandler = BeanMapFactory.CreateBeanMapSetHandler(targetType);

                    DynamicCacheFactory<string, BeanMapFactory.SetBeanHandler>.Instance.AddValue(setkey, setHandler);
                }
            }
            finally
            {
                DynamicCacheFactory<string, BeanMapFactory.SetBeanHandler>.Instance.WriteUnlock();
            }

            BeanMapFactory.GetBeanHandler getHandler = null;


            DynamicCacheFactory<string, BeanMapFactory.GetBeanHandler>.Instance.WriteLock();

            try
            {
                if (DynamicCacheFactory<string, BeanMapFactory.GetBeanHandler>.Instance.Contains(getkey))
                {
                    getHandler = DynamicCacheFactory<string, BeanMapFactory.GetBeanHandler>.Instance.GetValue(getkey);
                }

                if (getHandler == null)
                {
                    getHandler = BeanMapFactory.CreateBeanMapGetHandler(targetType);

                    DynamicCacheFactory<string, BeanMapFactory.GetBeanHandler>.Instance.AddValue(getkey, getHandler);
                }
            }
            finally
            {
                DynamicCacheFactory<string, BeanMapFactory.GetBeanHandler>.Instance.WriteUnlock();
            }

            return new BeanMap(target, targetType, getHandler, setHandler);
        }

        /// <summary>
        /// 创建一个纯的pojo对象
        /// 不支持数组的默认初始化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T CreatePojo<T>()
        {
            return (T)CreatePojo(typeof(T));
        }

        /// <summary>
        /// 创建一个纯的pojo对象
        /// 包含serializable+xmlroot
        /// 继承接口、IClonable
        /// 不支持数组的默认初始化
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object CreatePojo(Type interfaceType)
        {
            if (interfaceType == null)
                return null;

            ICloneable pojo = null;

            string key = StringHelper.default_name_cache_pojo + interfaceType.Namespace + interfaceType.FullName + interfaceType.Name;

            DynamicCacheFactory<string, ICloneable>.Instance.WriteLock();

            try
            {
                if (DynamicCacheFactory<string, ICloneable>.Instance.Contains(key))
                {
                    pojo = DynamicCacheFactory<string, ICloneable>.Instance.GetValue(key);
                }
                else
                {
                    pojo = PojoFactory.CreatePojo(interfaceType) as ICloneable;

                    DynamicCacheFactory<string, ICloneable>.Instance.AddValue(key, pojo);
                }
            }
            finally
            {
                DynamicCacheFactory<string, ICloneable>.Instance.WriteUnlock();
            }

            return pojo.Clone();
        }

        /// <summary>
        /// 创建透明代理
        /// 包含接口所有标签+serializable+xmlroot
        /// 继承IClonable / 接口
        /// </summary>
        /// <param name="interfaceType"></param>
        /// <returns></returns>
        internal static object CreateTransparentProxy(Type interfaceType)
        {
            if (interfaceType == null)
                return null;

            ICloneable proxy = null;

            string key = StringHelper.default_name_cache_proxy + interfaceType.Namespace + interfaceType.FullName + interfaceType.Name;

            DynamicCacheFactory<string, ICloneable>.Instance.WriteLock();
            try
            {
                if (DynamicCacheFactory<string, ICloneable>.Instance.Contains(key))
                {
                    proxy = DynamicCacheFactory<string, ICloneable>.Instance.GetValue(key);
                }
                else
                {
                    proxy = DynamicProxyFactory.CreateProxy(interfaceType) as ICloneable;

                    DynamicCacheFactory<string, ICloneable>.Instance.AddValue(key, proxy);
                }
            }
            finally
            {
                DynamicCacheFactory<string, ICloneable>.Instance.WriteUnlock();
            }

            return proxy.Clone();
        }
    }
}
